#include "stdafx.h"

#include "CPkgFile.h"
#include "CPackage.h"
#include <algorithm>
#include <string>

using namespace std;

namespace ArkCommon
{
	namespace Package
	{
		enum { openfail=1,packagefail=2,openfailinpackage=3, extend };

		CPkgFile::CPkgFile()
		{
			_file_handle=0;
			_offset=0;
			_position=0;
			_length=0;
		}

		CPkgFile::CPkgFile(const char* name,bool binary)
		{
			_file_handle=0;
			_offset=0;
			_position=0;
			_length=0;
			Open(name,binary);
		}

		CPkgFile::~CPkgFile()
		{
			Close();
		}

		void CPkgFile::Close()
		{
			if (IsValid())
			{
				//::CloseHandle((HANDLE)_file_handle);
				fclose((FILE*)_file_handle);
				_file_handle=0;
				_position=0;
				_offset=0;
			}
		}

		int CPkgFile::Seek(int pos,int origin)
		{
			if (!IsValid())
			{
				return -1;
			}

			int newpos;

			switch(origin)
			{
			case SEEK_SET:
				newpos=pos;
				break;
			case SEEK_END:
				newpos=_length+pos;
				break;
			case SEEK_CUR:
				newpos=_position+pos;
				break;
			default:
				//GenErr("Invalid seek origin.");
				break;
			}
			if((newpos<0) || (newpos>=_length))
				return -1;

			if (_position!=newpos)
			{
				_position=newpos;
				//::SetFilePointer((HANDLE)_file_handle,_position+_offset,0,FILE_BEGIN);
				return fseek( (FILE*)_file_handle,_position+_offset,SEEK_SET );
			}

			return 0;
		}

		int CPkgFile::Read(void *buffer,size_t len)
		{
			if (!IsValid())
			{
				return 0;
			}
			int newp=_position+len;
			if (newp>_length)
			{ 
				newp=_length;
			}
			len=newp-_position;
			unsigned int bytes;
			//	if (::ReadFile((HANDLE)_file_handle,buffer,len,&bytes,0)==0) {
			//		return 0;
			//	}
			bytes=fread(buffer,1,len,(FILE*)_file_handle);
			_position=newp;
			//assert(bytes==len);
			return bytes;
		}


		int CPkgFile::Open(const char *fullname,bool binary)
		{
			Close();

			const char* filename=fullname;
	
			//	HANDLE fh=::CreateFile(filename,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
			FILE *fh=fopen(filename,binary?"rb":"r");
			//if (fh!=INVALID_HANDLE_VALUE) {
			if (fh)
			{
				_file_handle=(void*)fh;
				_offset=0;
				fseek( fh,0,SEEK_END );
				_length=ftell(fh);
				fseek( fh,0,SEEK_SET );
				//_length=filelength(fileno(::GetFileSize(fh,0);
				_position=0;
				return 1;
			}
            return 0;

            /*
			string sFullName(fullname);
			string sPkgName;
			string sFileName;
			string::size_type pos;
			pos=sFullName.find_first_of("\\/");
			if( (pos==string::npos) || (pos+2>=sFullName.size()) )
			{
				return openfail;
			}
			sPkgName=sFullName.substr(0,pos);
			sPkgName+=string(".wd");
			sFileName=sFullName.substr(pos+1);

			const CPackage *p=CPackage::Load((sPkgName+"f").c_str());

			if (!p)
				return packagefail;
			
			filename=p->Open(sFileName.c_str(),&_offset,&_length);
			if (filename==0)
			{
				// try wd1, wd2 ...
				for (int i='1';;i++)
				{
					if (i>'9')
						i='a';
					p=CPackage::Load((sPkgName+char(i)).c_str());
					if (p==0)
						return openfailinpackage;
					filename=p->Open(sFileName.c_str(),&_offset,&_length);
					if (filename!=0)
					{
						break;
					}
				}
			}

			_position=0;
			//	_file_handle=(void*)::CreateFile(filename,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
			_file_handle=(void*)::fopen(filename,"rb");
			fseek(static_cast<FILE*>(_file_handle),_offset,SEEK_SET);
			
			return 0;
            */
		}

	}
}
